package autokeyboard.gui;

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.FocusAdapter;
import java.awt.event.FocusEvent;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.util.ArrayList;

import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.table.DefaultTableCellRenderer;

import autokeyboard.data.DataAccess;
import autokeyboard.data.KeyConverter;
import autokeyboard.data.PicturePanel;
import autokeyboard.data.TableModel;
import autokeyboard.handler.ShowDialogEvent;

@SuppressWarnings("serial")
public class ImportFileDialog extends JDialog
{
	private JFrame				frame;
	private JTable				table;
	private ArrayList<Object[]>	listObject;
	private PicturePanel		picPanel			= new PicturePanel();

	private JPanel				panelBrowse			= new JPanel(null);
	private JScrollPane			scroll				= new JScrollPane();
	private JPanel				panelDelayButton	= new JPanel(null);
	private JPanel				panelDelay			= new JPanel(null);
	private JPanel				panelButton			= new JPanel(null);

	private JTextField			tfBrowse			= new JTextField(40);
	private JTextField			tfDelay				= new JTextField(10);

	private JButton				btBrowse			= new JButton();
	private JButton				btSetDelay			= new JButton();
	private JButton				btImport			= new JButton();
	private JButton				btCancel			= new JButton();

	private JTextArea			previewTextArea		= new JTextArea();
	private ShowDialogEvent		showDlg				= new ShowDialogEvent();
	private DataAccess			dataAccess			= new DataAccess();
	private KeyConverter		converter			= new KeyConverter();
	private TableModel			model				= new TableModel();

	public ImportFileDialog(JFrame frame, JTable table, ArrayList<Object[]> listObject)
	{
		super(frame, true);
		this.frame = frame;
		this.table = table;
		this.listObject = listObject;

		initComponent();
		setDialogProperties();
	}

	private void setDialogProperties()
	{
		this.setSize(600, 400);
		this.setTitle("Import text file");
		this.setResizable(false);
		this.setDefaultCloseOperation(DISPOSE_ON_CLOSE);
		this.setLocationRelativeTo(frame);
		this.setIconImage(frame.getIconImage());
	}

	private void initComponent()
	{
		setButtonProperties();
		setTextFieldProperties();
		setScrollTextAreaProperties();

		setMainLayout();
		setLayoutPanelBrowse();
		setLayoutPanelDelayButton();

		keyEvent();
		tfKeyEvent();
		focusEvent();
		buttonEvent();
	}

	private void setButtonProperties()
	{
		btBrowse.setFont(new Font("Calibri", 0, 20));
		btBrowse.setText("Browse");

		btSetDelay.setFont(btBrowse.getFont());
		btSetDelay.setText("Set delay");

		btImport.setFont(btBrowse.getFont());
		btImport.setText("Import");
		btImport.setEnabled(false);

		btCancel.setFont(btBrowse.getFont());
		btCancel.setText("Cancel");

	}

	private void setTextFieldProperties()
	{
		tfBrowse.setFont(new Font("Calibri", 0, 16));
		tfBrowse.setEditable(false);

		tfDelay.setFont(tfBrowse.getFont());
		tfDelay.setText("50");
	}

	private void setScrollTextAreaProperties()
	{
		scroll.setPreferredSize(new Dimension(600, 300));
		scroll.setViewportView(previewTextArea);

		previewTextArea.setEditable(false);
		previewTextArea.setFont(new Font("Calibri", 0, 20));
		previewTextArea.setLineWrap(true);
		previewTextArea.setWrapStyleWord(true);

	}

	private void setMainLayout()
	{
		this.add(picPanel);
		picPanel.setLayout(new BorderLayout());
		picPanel.add(panelBrowse, BorderLayout.NORTH);
		picPanel.add(scroll, BorderLayout.CENTER);
		picPanel.add(panelDelayButton, BorderLayout.SOUTH);
		picPanel.path = "/Background/Import.png";
		picPanel.repaint();
	}

	private void setLayoutPanelBrowse()
	{
		panelBrowse.setPreferredSize(new Dimension(600, 50));
		panelBrowse.setLayout(new FlowLayout(FlowLayout.CENTER));
		panelBrowse.setOpaque(false);
		panelBrowse.add(tfBrowse);
		panelBrowse.add(btBrowse);

	}

	private void setLayoutPanelDelayButton()
	{
		panelDelayButton.setPreferredSize(new Dimension(600, 50));
		panelDelay.setPreferredSize(new Dimension(280, 50));
		panelButton.setPreferredSize(new Dimension(300, 50));

		panelDelayButton.setOpaque(false);
		panelDelay.setOpaque(false);
		panelButton.setOpaque(false);

		panelDelayButton.setLayout(new FlowLayout(FlowLayout.LEFT));
		panelDelay.setLayout(new FlowLayout(FlowLayout.LEFT));
		panelButton.setLayout(new FlowLayout(FlowLayout.RIGHT));

		panelDelayButton.add(panelDelay);
		panelDelayButton.add(panelButton);

		panelDelay.add(tfDelay);
		panelDelay.add(btSetDelay);

		panelButton.add(btImport);
		panelButton.add(btCancel);
	}

	/**
	 * This method will add keyEvent for all your component that use to press
	 * Escape key
	 */
	private void keyEvent()
	{
		JButton[] listButtons = { btBrowse, btCancel, btImport, btSetDelay };
		JTextField[] listTextFields = { tfBrowse, tfDelay };

		for (final JButton button : listButtons)
		{
			button.addKeyListener(new KeyAdapter()
			{
				@Override
				public void keyPressed(KeyEvent evt)
				{
					if (evt.getKeyCode() == KeyEvent.VK_ESCAPE) dispose();
				}
			});
		}

		for (final JTextField textField : listTextFields)
		{
			textField.addKeyListener(new KeyAdapter()
			{
				@Override
				public void keyPressed(KeyEvent evt)
				{
					if (evt.getKeyCode() == KeyEvent.VK_ESCAPE) dispose();
				}
			});
		}
	}

	/**
	 * This method will add event to all your button
	 */
	private void buttonEvent()
	{
		btBrowse.addActionListener(new ActionListener()
		{

			@Override
			public void actionPerformed(ActionEvent e)
			{
				showDlg.showOpenImport(frame);
				tfBrowse.setText(showDlg.getFileName());
				previewTextArea.setText(dataAccess.readFile(tfBrowse.getText()));
			}
		});
		
		btSetDelay.addActionListener(new ActionListener()
		{
			
			@Override
			public void actionPerformed(ActionEvent e)
			{
				btImport.setEnabled(true);
			}
		});

		btImport.addActionListener(new ActionListener()
		{

			@Override
			public void actionPerformed(ActionEvent e)
			{
				setDataToTable();
				dispose();
			}
		});

		btCancel.addActionListener(new ActionListener()
		{

			@Override
			public void actionPerformed(ActionEvent e)
			{
				dispose();
			}
		});

	}

	/**
	 * This method will add key event for your text field
	 */
	private void tfKeyEvent()
	{
		tfDelay.addKeyListener(new KeyAdapter()
		{
			@Override
			public void keyPressed(KeyEvent evt)
			{
				/**
				 * Check whether your input is a number. If it is not a number.
				 * It will delete your input
				 */
				if (!isValidNumber(tfDelay.getText()) && tfDelay.getText().length() != 0)
				{
					tfDelay.setText(tfDelay.getText().substring(0, tfDelay.getText().length() - 1));
				}
			}

			@Override
			public void keyReleased(KeyEvent evt)
			{
				/**
				 * Check whether your input is a number. If it is not a number.
				 * It will delete your input
				 */
				if (!isValidNumber(tfDelay.getText()) && tfDelay.getText().length() != 0)
				{
					tfDelay.setText(tfDelay.getText().substring(0, tfDelay.getText().length() - 1));
				}
				else if (isValidNumber(tfDelay.getText()) && tfDelay.getText().length() != 0)
				{
					try
					{
						int number = Integer.parseInt(tfDelay.getText());
						if (number < 1)
						{
							tfDelay.setText("1");
						}
					} catch (Exception ex)
					{
					}
				}
			}
		});
	}

	/**
	 * This method will check whether your input is number or not.
	 * 
	 * @param text
	 * @return
	 */
	private boolean isValidNumber(String text)
	{
		if (text.length() != 0)
		{
			char[] list = text.toCharArray();
			for (char item : list)
			{
				if (!Character.isDigit(item)) return false;
			}
		}
		return true;
	}

	/**
	 * This method will addFocusListener for tfDelay
	 * <p>
	 * When tfDelay is lost focus it will check whether tfDelay had a value or
	 * not. Unless it had a value this will set the default value is 50 to that
	 * text field
	 */
	private void focusEvent()
	{
		tfDelay.addFocusListener(new FocusAdapter()
		{
			@Override
			public void focusLost(FocusEvent e)
			{
				if (tfDelay.getText().length() == 0)
				{
					tfDelay.setText("50");
				}
			}

			@Override
			public void focusGained(FocusEvent e)
			{
				tfDelay.setSelectionStart(0);
				tfDelay.setSelectionEnd(tfDelay.getText().length());
			}
		});
	}

	/**
	 * This method will set your new table with your import text
	 * <p>
	 * It also fill data to your listObject
	 */
	private void setDataToTable()
	{
		while(listObject.size() != 0)
		{
			listObject.remove(0);
		}
		
		String textData = previewTextArea.getText();
		int delay = Integer.parseInt(tfDelay.getText());
		for (int i = 0; i < textData.length(); i++)
		{
			listObject.add(converter.converter(Character.toString(textData.charAt(i)), delay));
		}

		Object[][] list = new Object[listObject.size()][];
		for (int i = 0; i < listObject.size(); i++)
		{
			list[i] = listObject.get(i);
		}

		table.setModel(model.setNewModel(list));
		columnAlignment(JLabel.LEFT);
		if(listObject.size() == 0)
			TablePanel.isChanged = false;
		else
			TablePanel.isChanged = true;
	}

	/**
	 * This method will align your column in your table with your input
	 * alignment
	 * 
	 * @param alignment
	 */
	private void columnAlignment(int alignment)
	{
		DefaultTableCellRenderer cellRenderer = new DefaultTableCellRenderer();
		cellRenderer.setHorizontalAlignment(alignment);
		table.getColumnModel().getColumn(0).setCellRenderer(cellRenderer);
		table.getColumnModel().getColumn(1).setCellRenderer(cellRenderer);
		table.getColumnModel().getColumn(2).setCellRenderer(cellRenderer);
		table.getColumnModel().getColumn(3).setCellRenderer(cellRenderer);
	}
}
